/*
 * FeedAnalyzer.java
 *
 * Created on December 4, 2006, 12:06 PM
 */
package spring;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.regex.*;
import javax.swing.text.html.HTMLDocument;

/**
 *
 * @author  spring
 */
public class FeedAnalyzer extends javax.swing.JFrame {

    /** Creates new form FeedAnalyzer */
    public FeedAnalyzer() {
        initComponents();
        setDefaults();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        DistMeasure = new javax.swing.ButtonGroup();
        jSplitPane1 = new javax.swing.JSplitPane();
        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        FeedList = new javax.swing.JList();
        jPanel2 = new javax.swing.JPanel();
        TabPanel = new javax.swing.JTabbedPane();
        TextComp = new javax.swing.JScrollPane();
        Disp = new javax.swing.JTextArea();
        HTMLComp = new javax.swing.JScrollPane();
        HtmlDisp = new javax.swing.JEditorPane();
        PlotComp = new javax.swing.JScrollPane();
        pP1 = new spring.PlotPanel1();
        PlotCompFin = new javax.swing.JScrollPane();
        pP2 = new spring.PlotPanel2();
        POIComp = new javax.swing.JScrollPane();
        pPP1 = new spring.PlotPanelPOI();
        jPanel3 = new javax.swing.JPanel();
        LoadFeeds = new javax.swing.JButton();
        ClearDisplay = new javax.swing.JButton();
        RetrieveFeed = new javax.swing.JButton();
        RetrieveAllFeeds = new javax.swing.JButton();
        RemoveFeed = new javax.swing.JButton();
        SaveFeeds = new javax.swing.JButton();
        AddFeed = new javax.swing.JButton();
        GetFeedInfo = new javax.swing.JButton();
        GetEntryInfo = new javax.swing.JButton();
        GetRawFeed = new javax.swing.JButton();
        Feed = new javax.swing.JLabel();
        FeedToAdd = new javax.swing.JTextField();
        Exit = new javax.swing.JButton();
        LoadRSS = new javax.swing.JButton();
        ReoadRSS = new javax.swing.JButton();
        ClearEditor = new javax.swing.JButton();
        HashOneFeedEntries = new javax.swing.JButton();
        Plot = new javax.swing.JButton();
        LoadPOI = new javax.swing.JButton();
        PDist = new javax.swing.JRadioButton();
        EDist = new javax.swing.JRadioButton();
        RSSList = new javax.swing.JLabel();
        FeedAnalysis = new javax.swing.JLabel();
        HTML = new javax.swing.JLabel();
        PlotL = new javax.swing.JLabel();
        HashAllFeeds = new javax.swing.JButton();
        LoadDocVec = new javax.swing.JButton();
        RateL = new javax.swing.JLabel();
        Rate = new javax.swing.JTextField();
        IterL = new javax.swing.JLabel();
        Iter = new javax.swing.JTextField();
        ErrorL = new javax.swing.JLabel();
        Error = new javax.swing.JTextField();
        jLabel2 = new javax.swing.JLabel();
        KMeans = new javax.swing.JButton();
        ClearPoiPlot = new javax.swing.JButton();
        SavePoiPos = new javax.swing.JButton();
        HashAllFeedEntries = new javax.swing.JButton();
        PoiPower = new javax.swing.JLabel();
        POIMag = new javax.swing.JTextField();
        HashProg = new javax.swing.JProgressBar();
        MagSlider = new javax.swing.JSlider();
        FeedLoadProg = new javax.swing.JProgressBar();
        jSeparator1 = new javax.swing.JSeparator();
        jSeparator2 = new javax.swing.JSeparator();
        jSeparator3 = new javax.swing.JSeparator();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        NClusters = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jSeparator4 = new javax.swing.JSeparator();
        KMeansCB = new javax.swing.JCheckBox();
        EditPOISet = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.GridBagLayout());

        jSplitPane1.setDividerLocation(100);
        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        jPanel1.setLayout(new java.awt.GridBagLayout());

        jLabel1.setText("Feeds");
        jPanel1.add(jLabel1, new java.awt.GridBagConstraints());

        FeedList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Feeds" };
            public int getSize() { return strings.length; }
            public Object getElementAt(int i) { return strings[i]; }
        });
        jScrollPane2.setViewportView(FeedList);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPanel1.add(jScrollPane2, gridBagConstraints);

        jSplitPane1.setLeftComponent(jPanel1);

        jPanel2.setPreferredSize(new java.awt.Dimension(600, 600));
        jPanel2.setLayout(new java.awt.GridLayout(1, 0));

        TabPanel.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT);
        TabPanel.setPreferredSize(new java.awt.Dimension(300, 300));

        Disp.setColumns(20);
        Disp.setRows(5);
        TextComp.setViewportView(Disp);

        TabPanel.addTab("Text", TextComp);

        HtmlDisp.setContentType("text/html");
        HtmlDisp.setEditable(false);
        HtmlDisp.setText("<html>\r   <head>\r \r   </head>\r   <body>\r     <p style=\"margin-top: 0\">\r Some Stuff      \r     </p>\r   </body>\r </html>\r ");
        HtmlDisp.addHyperlinkListener(new javax.swing.event.HyperlinkListener() {
            public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {
                HtmlDispHyperlinkUpdate(evt);
            }
        });
        HTMLComp.setViewportView(HtmlDisp);

        TabPanel.addTab("HTML", HTMLComp);

        pP1.setLayout(null);
        PlotComp.setViewportView(pP1);

        TabPanel.addTab("G1", PlotComp);

        pP2.setLayout(null);
        PlotCompFin.setViewportView(pP2);

        TabPanel.addTab("G2", PlotCompFin);

        pPP1.setLayout(null);
        POIComp.setViewportView(pPP1);

        TabPanel.addTab("POI", POIComp);

        jPanel2.add(TabPanel);

        jSplitPane1.setRightComponent(jPanel2);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(jSplitPane1, gridBagConstraints);

        jPanel3.setLayout(new java.awt.GridBagLayout());

        LoadFeeds.setText("Load Feeds");
        LoadFeeds.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                LoadFeedsActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(LoadFeeds, gridBagConstraints);

        ClearDisplay.setText("Clear Text Display");
        ClearDisplay.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ClearDisplayActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 12;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(ClearDisplay, gridBagConstraints);

        RetrieveFeed.setText("Retrieve Feed");
        RetrieveFeed.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                RetrieveFeedActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(RetrieveFeed, gridBagConstraints);

        RetrieveAllFeeds.setText("Retrieve All Feeds");
        RetrieveAllFeeds.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                RetrieveAllFeedsActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(RetrieveAllFeeds, gridBagConstraints);

        RemoveFeed.setText("Remove Feed");
        RemoveFeed.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                RemoveFeedActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(RemoveFeed, gridBagConstraints);

        SaveFeeds.setText("Save Feeds");
        SaveFeeds.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        SaveFeeds.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SaveFeedsActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(SaveFeeds, gridBagConstraints);

        AddFeed.setText("AddFeed");
        AddFeed.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                AddFeedActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(AddFeed, gridBagConstraints);

        GetFeedInfo.setText("Get Feed Info");
        GetFeedInfo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                GetFeedInfoActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(GetFeedInfo, gridBagConstraints);

        GetEntryInfo.setText("Get Entry Info");
        GetEntryInfo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                GetEntryInfoActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 11;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(GetEntryInfo, gridBagConstraints);

        GetRawFeed.setText("Get Raw Feed");
        GetRawFeed.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                GetRawFeedActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(GetRawFeed, gridBagConstraints);

        Feed.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        Feed.setText("Feeds");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(Feed, gridBagConstraints);

        FeedToAdd.setText("FeedURL");
        FeedToAdd.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                FeedToAddActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(FeedToAdd, gridBagConstraints);

        Exit.setText("Exit");
        Exit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ExitActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 32;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(Exit, gridBagConstraints);

        LoadRSS.setText("Load RSS");
        LoadRSS.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                LoadRSSActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(LoadRSS, gridBagConstraints);

        ReoadRSS.setText("Reload RSS");
        ReoadRSS.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ReoadRSSActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(ReoadRSS, gridBagConstraints);

        ClearEditor.setText("Clear Editor");
        ClearEditor.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ClearEditorActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 11;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(ClearEditor, gridBagConstraints);

        HashOneFeedEntries.setText("Index Entries for a Feed");
        HashOneFeedEntries.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                HashOneFeedEntriesActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(HashOneFeedEntries, gridBagConstraints);

        Plot.setText("Plot Entries");
        Plot.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                PlotActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 28;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(Plot, gridBagConstraints);

        LoadPOI.setText("Load POI");
        LoadPOI.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                LoadPOIActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(LoadPOI, gridBagConstraints);

        DistMeasure.add(PDist);
        PDist.setSelected(true);
        PDist.setText("Pearson Distance");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 26;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(PDist, gridBagConstraints);

        DistMeasure.add(EDist);
        EDist.setText("Euclidian Distance");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 25;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(EDist, gridBagConstraints);

        RSSList.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        RSSList.setText(" Feed List");
        RSSList.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(RSSList, gridBagConstraints);

        FeedAnalysis.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        FeedAnalysis.setText("Index Creation");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 14;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(FeedAnalysis, gridBagConstraints);

        HTML.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        HTML.setText("HTML");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(HTML, gridBagConstraints);

        PlotL.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        PlotL.setText("Plot");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 15;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(PlotL, gridBagConstraints);

        HashAllFeeds.setText("Index All Feeds");
        HashAllFeeds.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                HashAllFeedsActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 16;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(HashAllFeeds, gridBagConstraints);

        LoadDocVec.setText("Load Docs");
        LoadDocVec.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                LoadDocVecActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 17;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(LoadDocVec, gridBagConstraints);

        RateL.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        RateL.setText("Rate");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 27;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(RateL, gridBagConstraints);

        Rate.setText("0.001");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 27;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(Rate, gridBagConstraints);

        IterL.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        IterL.setText("Iterations");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 29;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(IterL, gridBagConstraints);

        Iter.setText("0");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 29;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(Iter, gridBagConstraints);

        ErrorL.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        ErrorL.setText("Total Error");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 30;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(ErrorL, gridBagConstraints);

        Error.setText("0");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 30;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(Error, gridBagConstraints);

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel2.setText("POI Plotting");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 14;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jLabel2, gridBagConstraints);

        KMeans.setText("K-Means Analysis");
        KMeans.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                KMeansActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 26;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(KMeans, gridBagConstraints);

        ClearPoiPlot.setText("Clear POI Panel");
        ClearPoiPlot.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ClearPoiPlotActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 18;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(ClearPoiPlot, gridBagConstraints);

        SavePoiPos.setText("Save POI Info");
        SavePoiPos.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                SavePoiPosActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 16;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(SavePoiPos, gridBagConstraints);

        HashAllFeedEntries.setText("Index Entries for All Feeds");
        HashAllFeedEntries.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                HashAllFeedEntriesActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 17;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel3.add(HashAllFeedEntries, gridBagConstraints);

        PoiPower.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        PoiPower.setText("Magnification");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 19;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(PoiPower, gridBagConstraints);

        POIMag.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        POIMag.setText("10");
        POIMag.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                POIMagActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 20;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(POIMag, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 18;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(HashProg, gridBagConstraints);

        MagSlider.setForeground(new java.awt.Color(0, 0, 0));
        MagSlider.setValue(10);
        MagSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                MagSliderStateChanged(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 21;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel3.add(MagSlider, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(FeedLoadProg, gridBagConstraints);

        jSeparator1.setBackground(java.awt.Color.darkGray);
        jSeparator1.setMinimumSize(new java.awt.Dimension(0, 10));
        jSeparator1.setOpaque(true);
        jSeparator1.setPreferredSize(new java.awt.Dimension(0, 10));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 13;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jSeparator1, gridBagConstraints);

        jSeparator2.setBackground(java.awt.Color.darkGray);
        jSeparator2.setForeground(new java.awt.Color(255, 255, 255));
        jSeparator2.setMinimumSize(new java.awt.Dimension(0, 10));
        jSeparator2.setOpaque(true);
        jSeparator2.setPreferredSize(new java.awt.Dimension(0, 10));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 31;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jSeparator2, gridBagConstraints);

        jSeparator3.setBackground(java.awt.Color.darkGray);
        jSeparator3.setMinimumSize(new java.awt.Dimension(0, 10));
        jSeparator3.setOpaque(true);
        jSeparator3.setPreferredSize(new java.awt.Dimension(0, 10));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jSeparator3, gridBagConstraints);

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel3.setText("MultiDimensional Scaling");
        jLabel3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 24;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jLabel3, gridBagConstraints);

        jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel4.setText("Clusters");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 25;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jLabel4, gridBagConstraints);

        NClusters.setText("7");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 25;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(NClusters, gridBagConstraints);

        jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel5.setText("Statistcal Analysis");
        jLabel5.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 23;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jLabel5, gridBagConstraints);

        jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel6.setText("Clustering");
        jLabel6.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 24;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jLabel6, gridBagConstraints);

        jSeparator4.setBackground(java.awt.Color.darkGray);
        jSeparator4.setMinimumSize(new java.awt.Dimension(0, 10));
        jSeparator4.setOpaque(true);
        jSeparator4.setPreferredSize(new java.awt.Dimension(0, 10));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 22;
        gridBagConstraints.gridwidth = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(jSeparator4, gridBagConstraints);

        KMeansCB.setText("KMeans Vector");
        KMeansCB.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                KMeansCBActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 27;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(KMeansCB, gridBagConstraints);

        EditPOISet.setText("Edit POI Set");
        EditPOISet.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                EditPOISetActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 28;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPanel3.add(EditPOISet, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        getContentPane().add(jPanel3, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents
    private void GetEntryInfoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_GetEntryInfoActionPerformed
    // Requires Retrieve Feed execution
    // Writes the output to the Text tab
        TabPanel.setSelectedComponent(TextComp);
        
        /* Prints summary of the selected Feed */
        Disp.setText("");
        Disp.append("\nFeed Title = \t" + SFeed[curFeed].getTitle());
        Disp.append("\nFeed Author = \t" + SFeed[curFeed].getAuthor());
        Disp.append("\nFeed Copyright = \t" + SFeed[curFeed].getCopyright());
        Disp.append("\nFeed Encoding = \t" + SFeed[curFeed].getEncoding());
        Disp.append("\nFeed Link = \t" + SFeed[curFeed].getLink());
        
        /* Prints URL, RSS entities themselves and short descriptions*/
        for (Iterator iter = SFeed[curFeed].getEntries().listIterator(); iter.hasNext();) {
            SyndEntry myentry = (SyndEntry) iter.next();
            Disp.append("\nEntryTitle = " + myentry.getTitle());
            Disp.append("\nEntryLink = " + myentry.getLink());
            Disp.append("\nEntryDescription = " + myentry.getDescription().getValue());
        }
}//GEN-LAST:event_GetEntryInfoActionPerformed

    private void GetRawFeedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_GetRawFeedActionPerformed
    // Downloads raw feed xml of the selected feed and displays in the Text tab.

        boolean ok = false;
        int amtread = 0;
        char[] cbuf = new char[100];
        String feedname = (String) FeedList.getSelectedValue(); // gets the information about which Feed is selected
        try {
            URL feedUrl = new URL(feedname);
            XmlReader xr = new XmlReader(feedUrl); // connects to the URL
            while ((amtread = xr.read(cbuf)) != -1) {
                Disp.append(new String(cbuf, 0, amtread)); // Displaying on the Text tab raw xml
            }
            ok = true;
        } catch (IOException ex) {
            ex.printStackTrace();
            System.out.println("ERROR: " + ex.getMessage());
        }
}//GEN-LAST:event_GetRawFeedActionPerformed

    private void LoadFeedsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LoadFeedsActionPerformed
// Loading previously predefined sets of Feed Sources
// Provieds navigation on File System to choose a file with stored Feed Sources        
        int r;
        javax.swing.JFileChooser fc = new javax.swing.JFileChooser(".//data");
        javax.swing.filechooser.FileFilter imageFilter = new javax.swing.filechooser.FileFilter() {
            /* Applying filtering rules to display just files with the required extentions*/
            public boolean accept(File file) {
                String name = file.getName().toLowerCase();
                return name.endsWith(".flst");
            }

            public String getDescription() {
                return "Data Files";
            }
        };
        
        fc.setFileFilter(imageFilter);
        r = fc.showOpenDialog(this); //Pops up an "Open File" file chooser dialog
        if (r == javax.swing.JFileChooser.APPROVE_OPTION) {
            feedfile = fc.getSelectedFile();

            try {
                flm.clear();
                BufferedReader rssfeeds = new BufferedReader(new FileReader(feedfile));
                int i = 0;
                /* Trying to read stored RSS Feeds*/
                while ((FeedNames[i] = rssfeeds.readLine()) != null) {
                    flm.addElement(FeedNames[i]);
                    i++;
                }
                /* Feedlist is an object that displays the elements in the
                 specified array. It sets the model that represents the contents
                 or "value" of the list*/
                FeedList.setModel(flm);
                rssfeeds.close();
            } catch (FileNotFoundException fne) {
                System.out.println("LoadFeedsERROR: " + fne.getMessage());
                fne.printStackTrace();
            } catch (IOException ioe) {
                System.out.println("LoadFeedsERROR: " + ioe.getMessage());
                ioe.printStackTrace();
            }
        }
        
}//GEN-LAST:event_LoadFeedsActionPerformed

    private void GetFeedInfoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_GetFeedInfoActionPerformed
    // Prints general statistics on the Feed
    // Requires RetrieveFeed execution prior
        TabPanel.setSelectedComponent(TextComp); // selects Text tab
        Disp.setText("");
                        
        for (int i = 0; i <= nfeeds; i++) {
            Disp.append("\n\nFeed Title = \t" + SFeed[i].getTitle());
            Disp.append("\nAuthor = \t" + SFeed[i].getAuthor());
            Disp.append("\nCopyright = \t" + SFeed[i].getCopyright());
            Disp.append("\nEncoding = \t" + SFeed[i].getEncoding());
            Disp.append("\nLink = \t" + SFeed[i].getLink());
            Disp.append("\nNumber of Entries = \t" + SFeed[i].getEntries().size());
        }      
}//GEN-LAST:event_GetFeedInfoActionPerformed

    private void ExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ExitActionPerformed
// TODO add your handling code here:
        System.exit(0);
    }//GEN-LAST:event_ExitActionPerformed

    private void RetrieveFeedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RetrieveFeedActionPerformed
        /* The first action to work with the data from the selected RSS Feed.
        Parses the selected RSS Feed */
        TabPanel.setSelectedComponent(TextComp);
        Disp.setText("");
        boolean ok = false;
        /* Here the user chooses a feed from the Feed List. If nothing is
         selected - then the first entry is the default one*/
        String feedname = (String) FeedList.getSelectedValue();
        try {
            
            URL feedUrl = new URL(feedname);
            SFeed[curFeed] = SFInput.build(new XmlReader(feedUrl)); // parses the Feed
            ok = true;
        } catch (Exception ex) {
            System.out.println("RetrieveFeedActionERROR: " + ex.getMessage());
            ex.printStackTrace();

        }
        if (!ok) {
            Disp.append("Failed to retrieve feed: " + feedname + "\n");
        } 
        
}//GEN-LAST:event_RetrieveFeedActionPerformed

    private void ClearDisplayActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ClearDisplayActionPerformed
        // Cleans Text tab
        TabPanel.setSelectedComponent(TextComp);
        Disp.setText("");
}//GEN-LAST:event_ClearDisplayActionPerformed

    private void FeedToAddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_FeedToAddActionPerformed
    // TODO add your handling code here:
}//GEN-LAST:event_FeedToAddActionPerformed

    private void AddFeedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AddFeedActionPerformed
        /* adds a Feed URL to the Feed List, and after displays a newly
         modified Feed List          */
        flm.addElement(FeedToAdd.getText());
        FeedList.setModel(flm);
        
    }//GEN-LAST:event_AddFeedActionPerformed

    private void RemoveFeedActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RemoveFeedActionPerformed
        /* Gets the selected Feed line from the Feed List, removes it and
         displays the remaining elements          */
        int i = FeedList.getSelectedIndex();
        flm.removeElementAt(i);
        FeedList.setModel(flm);
    }//GEN-LAST:event_RemoveFeedActionPerformed

    private void SaveFeedsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SaveFeedsActionPerformed
        // Saves the Feeds, which are in the FeedList and displayed in the select menu
        try {
            BufferedWriter rssfeeds = new BufferedWriter(new FileWriter(feedfile));
            flm = (javax.swing.DefaultListModel) FeedList.getModel();
            for (int i = 0; i < flm.getSize(); i++) {
                rssfeeds.write((String) flm.getElementAt(i));
                rssfeeds.write("\n");
            }
            rssfeeds.close();
        } catch (FileNotFoundException fne) {
        } catch (IOException ioe) {
        }
              
        
    }//GEN-LAST:event_SaveFeedsActionPerformed

    private void RetrieveAllFeedsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RetrieveAllFeedsActionPerformed
        // Creates an array of structures - one for each feed, to be able to work with each of the feed
        /* It may take some time, depending on the number of Feeds in the FeedList
         to create XMLReader elements for each of it. To show busy situation
         mouse cursor changes its picture. At the end of function execution it
         comes back to the default one. */
        setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR) ); 
        // shows that the button is being pressed during the execution
        TabPanel.setSelectedComponent(TextComp);
        Disp.setText("");
        nfeeds = 0;
        // receives the list of items (Feeds), displayed in the FeedsList
        flm = (javax.swing.DefaultListModel) FeedList.getModel();
        FeedLoadProg.setMaximum(flm.getSize());
        for (int i = 0; i < flm.getSize(); i++) {
            FeedLoadProg.setValue(i);
            boolean ok = false;
            try {
                URL feedUrl = new URL((String) flm.getElementAt(i)); // get a single URL to work with
                SFeed[i] = SFInput.build(new XmlReader(feedUrl)); // parses a single RSS Feed
                ok = true;
                nfeeds++;
            } catch (Exception ex) {
                System.out.println("RetrievAllFeedsERROR: " + ex.getMessage());
                ex.printStackTrace();
            }
            if (!ok) {
                Disp.append("Failed to retrieve " + flm.getElementAt(i) + "feed.\n");
            }
        }//for  
         setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_RetrieveAllFeedsActionPerformed

    private void HtmlDispHyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {//GEN-FIRST:event_HtmlDispHyperlinkUpdate
        // TODO add your handling code here:

        if (evt.getEventType() == javax.swing.event.HyperlinkEvent.EventType.ACTIVATED) {
            try {
                HtmlDisp.setPage(evt.getURL());
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
        
    }//GEN-LAST:event_HtmlDispHyperlinkUpdate

    private void LoadRSSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LoadRSSActionPerformed
        // Loading the actual data from RSS feeds. Requires to have
        // RetrieveFeedActionPerformed executed prior to this 
        TabPanel.setSelectedComponent(HTMLComp); // sets HTML tab as active
        HtmlDisp.setText(buildHtmlString(curFeed));  
        
        
    }//GEN-LAST:event_LoadRSSActionPerformed

    private void ReoadRSSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ReoadRSSActionPerformed
        // TODO add your handling code here:
        TabPanel.setSelectedComponent(HTMLComp);
        HtmlDisp.setText(buildHtmlString(curFeed));   
    }//GEN-LAST:event_ReoadRSSActionPerformed

    private void ClearEditorActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ClearEditorActionPerformed
    //  clears HTML tab
        TabPanel.setSelectedComponent(HTMLComp);
        HtmlDisp.setText("");  
    }//GEN-LAST:event_ClearEditorActionPerformed

    /* Calculates frequencies of occurence of each word in the feed and generates
     an array. For each entry in the feed generates its vector of occurencies. Calculates
     correlation between intries in the feed. Requires execution of
     RetrieveFeedActionPerformed method first.*/
    private void HashOneFeedEntriesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_HashOneFeedEntriesActionPerformed
    
        String tmpstr;
        String[] entrywords;
        double[][] entryVec = new double[100][];

        TabPanel.setSelectedComponent(TextComp); // Selects Text tab 
        Disp.setText(""); // Clears text in Text tab
        feeds = false;
        entries = true;
        
        
        /* Build a hash map and a key set for the feed. HashMap will contain the
         number of occurences of each word in the Feed. If the word occured only
         once, or it is within the StopWord Array, it will be deleted from the
         HashMap, presenting a reduced HashMap. */
        HashMap FeedHM = createHashMap(buildHtmlString(curFeed));
        Set kc = FeedHM.keySet(); // Returns a set view of the keys contained in this map
        
        // Constructs a new HashMap with the same mappings as in FeedHM
        HashMap EntryHM = new HashMap(FeedHM);
        //Set ks = EntryHM.keySet();
        
        int feedentry = 0;
        HashProg.setValue(10); // Sets the progress bar value
        
        /* SFeed is already a parsed XML structure, (from RetrieveFeedActionPerformed method).
         As long as there can be several Feeds, we select to work with a specific one.
         We select all the entries in the feed, one by one
         */ 
        for (Iterator iter = SFeed[curFeed].getEntries().listIterator(); iter.hasNext();) {
            Iterator it = kc.iterator();
            
            /* kc is the set of keys for HashMap. So we walk through the keys and
             set values for the korresponding keys in EntryHM to 0*/
            while (it.hasNext()) {
                EntryHM.put((String) it.next(), new Integer(0));
            }
            
            SyndEntry oneEntry = (SyndEntry) iter.next(); // takes one entry from the feed
            Disp.append("\n" + oneEntry.getTitle() + "\n"); // displays the title of the entry
            EntryTitles[feedentry] = oneEntry.getTitle();
            Links[feedentry]=oneEntry.getLink();
            
            /*Remember: pattern tagPat is set to find tags,"<"+"some values"+">".
             So we will eliminate tags for the title and description, and split
             text into words*/
            Matcher docMatcher = tagPat.matcher(oneEntry.getTitle() + oneEntry.getDescription().getValue());
            tmpstr = docMatcher.replaceAll(" ");
            entrywords = tmpstr.toLowerCase().split("[\\s\\p{Punct}]+");
            
            /* create a hash of the frequency of word occurrence. at first we
             check, if the word is in the hash (if the word occures
             more than once in the document, or it is not a stopword) and
             increment index*/
            for (int i = 0; i < entrywords.length; i++) {
                pstem.add(entrywords[i].toCharArray(), entrywords[i].length());
                pstem.stem();
                tmpstr = pstem.toString();
                if (EntryHM.containsKey(tmpstr)) {
                    Integer storedVal = (Integer) EntryHM.get(tmpstr);
                    EntryHM.put(tmpstr, new Integer(storedVal.intValue() + 1));
                }
            }
            entryVec[feedentry] = createVector(EntryHM, kc);
            
            //Plot the vector of words occurence 
            Disp.append("\n" + printdvec(entryVec[feedentry]) + "\n");
            feedentry++;
        }
        
        HashProg.setValue(50); // Set the progress to 50%
        /* calculate, how entries in the feed correlate with each other or how
         far away in meanining they are (0 - total correlation, 1 - uncorrelated)*/
        distMatrix = createDistMatrix(feedentry, entryVec); 
        HashProg.setValue(75);
        
        /* stores the processed data in the .vec file. It stores a big vector of
         occurance (one for the whole feed; the structure is - word: occurence) 
         + for all the entities: the description, the link, and information about
         how many times each word from the big vector occured in the entity*/
        writeDocVecFile(curFeed, feedentry, entryVec, FeedHM);
        HashProg.setValue(100); // Progress is 100%, operation is completed
}//GEN-LAST:event_HashOneFeedEntriesActionPerformed
    
    /* Requires HashAllFeedsEntriesActionPerformed execution before. This method
     visually represents the similarity in meaning between the feed entries.
     It makes the projection of nD space on 2D. This method is eterative.
     
     On each step we randomly place s points, which represent the projection
     of nD into 2D. We calculate normalized distances (Dn = [0..1]) between all
     vectors in 2D and nD.
     If distance in nD > distance in 2D - we move 2 points apart.
     If distance in nD < distance in 2D - we move 2 points closer.
     If distance in nD = distance in 2D - we leave points on theirs places.
     
     And so on.
     We assume, that entries with close meaning will move togeather.
     */
    private void PlotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_PlotActionPerformed
        
        if (distMatrix == null) {
            TabPanel.setSelectedComponent(TextComp);
            Disp.setText("");
            Disp.append("\n\n You must load hashes before you can plot\n\n");
            return;
        }
        
        TabPanel.setSelectedComponent(PlotComp);
        int s = distMatrix.length;
        double[][] loc = new double[s][2];
        int DMErrors = 0, PMErrors = 0;
        
        /* we have s vectors in nD.
         we generate an array for initial placement of these vectors in 2D space*/

        for (int i = 0; i < s; i++) {
            loc[i][0] = Math.random() * .9 + .05;
            loc[i][1] = Math.random() * .9 + .05;
        }

        // pP1 - is a plot pannel, where all the data will be displayed
        pP1.setMatrix(loc); // copies matrix of location
        pP1.setAccess(this);
        pP1.repaint();

        int it;
        double[][] plotMatrix = new double[s][s];
        double[][] grad = new double[s][2];
        double lasterror = 0.0, totalerror = 0.0, errorcomp = 0.0;
        double d = 0.0;
        boolean first = true;
        
        // receives the index to adjust the position of vectors in 2D space
        rate = new Double(Rate.getText()).doubleValue();

        // iterate upto 1000 times to place the entries in 2D space
        for (it = 0; it < 1000; it++) {
            
            // find 2D plot distances between all the vectors
            for (int i = 0; i < s; i++) {
                for (int j = 0; j < s; j++) {
                    plotMatrix[i][j] = getDistance(loc[i], loc[j]);
                }
            }
            
            // initializes gradient array to adjust 2D positions
            for (int i = 0; i < s; i++) {
                grad[i][0] = 0.0;
                grad[i][1] = 0.0;
            }
            
            /* we project points from nD into 2D. */
            totalerror = 0.0;
            for (int j = 0; j < s; j++) {
                for (int k = 0; k < s; k++) {
                    if (j == k) {
                        continue;
                    }
                    
                    /* if 2 vectors appeared to be located too close one to another
                     in 2D, denominator becomes very small, which further may cause
                     division by zero problem. here we will avoid this situation */
                    if (plotMatrix[k][j] < 0.000001) {
                        PMErrors++;
                        continue;
                    }
                      
                    if (distMatrix[k][j] < 0.000001) {
                        DMErrors++;
                        errorcomp = plotMatrix[k][j];
                    } else {
                        errorcomp = (plotMatrix[k][j] - distMatrix[k][j]) / distMatrix[k][j];                    
                    }
                    
                    grad[j][0] += ((loc[j][0] - loc[k][0]) / plotMatrix[k][j]) * errorcomp;
                    grad[j][1] += ((loc[j][1] - loc[k][1]) / plotMatrix[k][j]) * errorcomp;
                    totalerror += Math.abs(errorcomp);
                }
            }

            if (!first && lasterror < totalerror) {
                /* in other words: if the error in the next step of adjustment
                 is bigger, than in the previous one - stop it. most probable reason
                 - the adjustment rate is too big and all further steps wont
                 decrease the error */
                break;
            }
            
            first = false;
            lasterror = totalerror;
            for (int j = 0; j < s; j++) {
                loc[j][0] -= rate * grad[j][0];
                loc[j][1] -= rate * grad[j][1];
                
                // we decide here, allow or not points in 2D go beyond the plot, which is [0..1]*[0..1]
                /*
                if (loc[j][0] < .2) {
                    loc[j][0] = .2;
                }
                if (loc[j][0] > .8) {
                    loc[j][0] = .8;
                }
                if (loc[j][1] < .1) {
                    loc[j][1] = .1;
                }
                if (loc[j][1] > .9) {
                    loc[j][1] = .9;
                } 
                */
            }
        }// end iteration for 1000
        
        Disp.append("\nTotal Iterations " + it + ": Total error = " + totalerror);
        Disp.append("\nTotal DM Errors " + DMErrors + ": Total PM Errors = " + PMErrors);
        Iter.setText(" " + it);
        java.text.DecimalFormat formval = new java.text.DecimalFormat("#0.00");
        Error.setText(" " + formval.format(totalerror));
        pP2.setMatrix(loc);
        pP2.setAccess(this);
        pP2.repaint();
}//GEN-LAST:event_PlotActionPerformed
    
    /* loads from a .poi file information about clusters or areas of interest
     and displays them on the screen. */
    private void LoadPOIActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LoadPOIActionPerformed

        TabPanel.setSelectedComponent(POIComp);
        
        //removes the existing POI buttons from the plot panel
        int ncomp = pPP1.getComponentCount();
        java.awt.Component[] cc = pPP1.getComponents();
        for (int i = 0; i < ncomp; i++) {
            if (cc[i].getClass().getName().contains("POIBut")) {
                pPP1.remove(cc[i]);
            }
        }
        
        //prompts to select a .poi file
        javax.swing.JFileChooser fc = new javax.swing.JFileChooser(".//data");
        javax.swing.filechooser.FileFilter imageFilter = new javax.swing.filechooser.FileFilter() {

            public boolean accept(File file) {
                String name = file.getName().toLowerCase();
                return name.endsWith(".poi");
            }

            public String getDescription() {
                return "POI Files";
            }
        };
        
        fc.setFileFilter(imageFilter);
        int r = fc.showOpenDialog(this);
        if (r == javax.swing.JFileChooser.APPROVE_OPTION) {
            poifile = fc.getSelectedFile();
            int i = 0;
            try {
                int mag = new Integer(POIMag.getText()).intValue();
                pPP1.setMag(mag);
                BufferedReader poi = new BufferedReader(new FileReader(poifile));
                String tmpstr;
                
                // reads the file, line by line, each line is a POI object
                while ((tmpstr = poi.readLine()) != null) {
                    String[] parts = tmpstr.split(",", 7);
                    pb[i] = new POIBut();
                    
                    // gets coordinates, color, title for a POI
                    pb[i].setcoords(pPP1, new Double(parts[0]).doubleValue(),
                            new Double(parts[1]).doubleValue());
                    pb[i].setBackground(new java.awt.Color(new Integer(parts[2]).intValue(),
                            new Integer(parts[3]).intValue(),new Integer(parts[4]).intValue()));
                    pb[i].setText(parts[5]);
                    pb[i].setNum(i);
                    
                    /* the last element in parts array consists of attributes,
                     which present the information (meaning) of a POI itself*/
                    String[] sv = parts[6].split(",");
                    HashMap hm = new HashMap();
                    for (int j = 0; j < sv.length - 1; j += 2) {
                        hm.put(sv[j], new Double(sv[j + 1]));
                    }
                    /* converts informational meaning of a POI (a set of
                     informational attributes in a hashmap) into a string and associates
                     the string with a POI object*/
                    pb[i].setPoiHashMap(hm); 
                    pb[i].addComponentListener(pPP1);
                    
                    // adds a POI object to a plot and repaint the plot
                    pPP1.add(pb[i], i);
                    pPP1.repaint();
                    i++;
                }
                npoi = i;
                poi.close();
            } catch (FileNotFoundException fne) {
                System.out.println("LoadPOIERROR: " + fne.getMessage());
                fne.printStackTrace();
            } catch (IOException ioe) {
                System.out.println("LoadPOIERROR: " + ioe.getMessage());
                ioe.printStackTrace();
            }
        }//end if         
}//GEN-LAST:event_LoadPOIActionPerformed

    private void HashAllFeedsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_HashAllFeedsActionPerformed
    /* Requires previous execution of RetrieveAllFeedsActionPerformed method.
     Generates ONE hash of */
        String FeedSetHStr = null;
        String tmpstr;
        String[] feedwords;
        double[][] feedVec = new double[100][];
        
        // Set active Tab to Text and clear all information in it
        TabPanel.setSelectedComponent(TextComp);
        Disp.setText("");
        
        feeds = true;
        entries = false;
        HashProg.setValue(0); // Sets the progress of operation to 0
        for (int i = 0; i < nfeeds; i++) {
            // takes the parsed structure from Rome for each feed and generates a single html document
            FeedSetHStr += buildHtmlString(i);
        }
        
        /* creates a hash and key set representing the frequencies as a whole
         (if the word occures once or it is a stopword - it does appear in the hash)*/
        HashMap TotalHM = createHashMap(FeedSetHStr);
        Set kc = TotalHM.keySet();
        
        HashProg.setValue(10); // sets the progress of operation to 10%
        
        // Constructs a new HashMap with the same mappings
        HashMap FeedHM = new HashMap(TotalHM);
        
        double prog;
        for (int n = 0; n < nfeeds; n++) {
            prog=50.0*((double)n/nfeeds);
            HashProg.setValue(10+(int)prog); // sets the progress of operation
            Iterator it = kc.iterator();
            
            // sets the frequency of occuurence to 0
            while (it.hasNext()) {
                FeedHM.put((String) it.next(), new Integer(0));
            }
            
            Disp.append("\n" + SFeed[n].getTitle() + "\n"); // prints the title for a feed
            
            /* constructs an html string for a  feed with the number n from the
             feed list, having parsed structure from Rome library as the input*/
            
            Matcher dm = tagPat.matcher(buildHtmlString(n));
            tmpstr = dm.replaceAll(" "); // replaces all tags with spaces
            feedwords = tmpstr.toLowerCase().split("[\\s\\p{Punct}]+"); // splits the text into words
            
            // create a hash of the frequency of word occurrence in the feed
            for (int i = 0; i < feedwords.length; i++) {
                pstem.add(feedwords[i].toCharArray(), feedwords[i].length());
                pstem.stem();
                tmpstr = pstem.toString();
                if (FeedHM.containsKey(tmpstr)) {
                    Integer storedVal = (Integer) FeedHM.get(tmpstr);
                    FeedHM.put(tmpstr, new Integer(storedVal.intValue() + 1));
                }
            }
            
            // generates a vector of word occurence for a feed froma a feedlist
            feedVec[n] = createVector(FeedHM, kc);
            Disp.append("\n" + printdvec(feedVec[n]) + "\n"); // prints vector of word occurences
        }

        // generates a a matrix of similarities between feeds (how close in meaning they are )
        distMatrix = createDistMatrix(nfeeds, feedVec); 
        HashProg.setValue(80);
        writeDocVecFile(-1, nfeeds, feedVec, TotalHM); // desplays the matrix of silmilarities
        HashProg.setValue(100);
}//GEN-LAST:event_HashAllFeedsActionPerformed
    
    /* requires to have .poi file loaded first. visualizes the relations between
     entities in the rss feeds and our interest. */
    private void LoadDocVecActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_LoadDocVecActionPerformed
        String tmpstr;
        HashMap hm = new HashMap();
        setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR) );
        Set kc = null;
        double[][] dv = new double[maxentries][];
        String[] names = new String[maxentries];
        String[] links = new String[maxentries];
        TabPanel.setSelectedComponent(POIComp);
        
        //remove the existing document buttons from the plot panel
        int ncomp = pPP1.getComponentCount();
        java.awt.Component[] cc = pPP1.getComponents();
        for (int i = 0; i < ncomp; i++) {
            if (cc[i].getClass().getName().contains("DVBut")) {
                pPP1.remove(cc[i]);
            }
        }
        
        // selects the vector file, which was obtained after indexing of the feeds
        javax.swing.JFileChooser fc = new javax.swing.JFileChooser(".//data");
        javax.swing.filechooser.FileFilter imageFilter = new javax.swing.filechooser.FileFilter() {

            public boolean accept(File file) {
                String name = file.getName().toLowerCase();
                return name.endsWith(".vec");
            }

            public String getDescription() {
                return "Document Vector Files";
            }
        };
        
        fc.setFileFilter(imageFilter);
        int r = fc.showOpenDialog(this);
        if (r == javax.swing.JFileChooser.APPROVE_OPTION) {
            vecfile = fc.getSelectedFile();
            try {
                ndocs = 0;
                BufferedReader docvec = new BufferedReader(new FileReader(vecfile));
                HashMap words = new HashMap();
                Iterator it;
                while ((tmpstr = docvec.readLine()) != null) {
                    if (tmpstr.length() < 2) {
                        kc = hm.keySet();
                    } else if (tmpstr.contains("|")) {
                        String[] parts = tmpstr.split("\\|");
                        names[ndocs] = parts[0];
                        links[ndocs] = parts[1];
                        words.clear();
                        if (parts.length > 2) {
                            
                            String vec[] = parts[2].split(",");
                            for (int l = 0; l < vec.length; l += 2) {
                                words.put(vec[l], new Double(vec[l + 1]));
                            }
                        }
                        dv[ndocs] = new double[kc.size()];
                        it = kc.iterator();
                        int j = 0;
                        while (it.hasNext()) {
                            String word = (String) it.next();
                            if (words.containsKey(word)) {
                                dv[ndocs][j] = ((Double) words.get(word)).doubleValue();
                            } else {
                                dv[ndocs][j] = 0.0;
                            }
                            j++;
                        } 
                        // the double to string conversion in printdvec is very computationally expensive
                        //  Disp.append("DV" + ndocs + " = "+ printdvec(dv[ndocs]) + "\n");
                        ndocs++;
                        } else {
                        String[] parts = tmpstr.split(",");
                        hm.put(parts[0], new Integer(parts[1]));
                    }
                }
                docvec.close();
            } catch (FileNotFoundException fne) {
                System.out.println("LoadDocVecERROR: " + fne.getMessage());
                fne.printStackTrace();
            } catch (IOException ioe) {
                System.out.println("LoadDocVecERROR: " + ioe.getMessage());
                ioe.printStackTrace();
            }
        }
        //create POI vectors
        
        double[][] poivec = new double[npoi][];
        for (int i = 0; i < npoi; i++) {
            java.util.ArrayList al = new java.util.ArrayList();
            HashMap phm = pb[i].getPoiHashMap();
            HashMap nphm = new HashMap();
            Iterator pit = phm.keySet().iterator();
            //System.out.println("PHM size = "+phm.size());
            while (pit.hasNext()) {
                String word = (String) pit.next();
                pstem.add(word.toCharArray(), word.length());
                pstem.stem();
                tmpstr = pstem.toString();
                nphm.put(tmpstr, phm.get(word));
            }
            Iterator it = kc.iterator();
            int j = 0;
            poivec[i] = new double[hm.size()];
            while (it.hasNext()) {
                String word = (String) it.next();
                if (nphm.containsKey(word)) {
                    poivec[i][j++] = ((Double) nphm.get(word)).doubleValue();
                } else {
                    poivec[i][j++] = 0.0;
                }
            }
            pb[i].setdoubleVector(poivec[i]);
        }
        //create the document vectors
        int x = pPP1.getWidth();
        int y = pPP1.getHeight();
        double[] loc = new double[2];
        for (int i = 0; i < ndocs; i++) {
            db[i] = new DVBut();
            db[i].setText(".");
            db[i].setdoubleVector(dv[i]);
            pPP1.add(db[i]);
            db[i].setToolTipText(names[i]);
            db[i].setLink(links[i]);
        // System.out.println("DVEC"+i+" = "+db[i].getToolTipText()+ printdvec(dv[i])+"\n");
        }
        int mag = db[0].getdoubleVector().length; 
        mag /= (int) Math.sqrt(mag);
        POIMag.setText(new Integer(mag).toString());
        //setting the value of Magslider will cause a call to plot docs, so we don;t do it manually
        MagSlider.setValue(new Integer(POIMag.getText()).intValue());
        pPP1.setMag(mag);
        pPP1.intializePOIPanel();
        setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
        // plotDocs(true);
}//GEN-LAST:event_LoadDocVecActionPerformed
    
    /* as the input, it takes .km file, after indexing entries in the rssfeeds.
     each indexed array for each entry we assume as a vector in nD space.
     our goal is to partition data into subsets with more or less close meaning.
     we place m cluster centers randomly and then adjust them to be perfectly in
     the midle of each cluster.
     vectors remain fixed in space, cluster centers are mobile.
     * 
     we calculate distances from each vector to each cluster center, then group
     vectors, which are closest to 1-st center, which are closest to the 2-nd and so on.
     we move each cluster center exactly to the middle of the group of vectors,
     which were closest to this particular cluster center.
     the process repeats untill cluster centers remain motionless.*/
    private void KMeansActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_KMeansActionPerformed
        // sets cursor to busy
        setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR) );
        
        String tmpstr;
        HashMap hm = new HashMap();
        Set kc = null;
        int nrows = 0;
        File clusterfile=null;
        File poisetfile=null;
        double[][] dv = new double[1500][];
        int vector;
        String[] names = new String[1500];
        TabPanel.setSelectedComponent(TextComp);
        Disp.setText("");
        
        /* removes the existing document buttons from the plot panel, opens a dialog
         to select the vector file, prepared from  */
        javax.swing.JFileChooser fc = new javax.swing.JFileChooser(".//data");
        javax.swing.filechooser.FileFilter vectorFilter = new javax.swing.filechooser.FileFilter() {

            public boolean accept(File file) {
                String name = file.getName().toLowerCase();
                return name.endsWith(".km");
            }

            public String getDescription() {
                return "Document Vector Files";
            }
        };
        
        fc.setFileFilter(vectorFilter);
        int r = fc.showOpenDialog(this);
        if (r == javax.swing.JFileChooser.APPROVE_OPTION) {
            clusterfile = fc.getSelectedFile();
            try {
                BufferedReader docvecreader = new BufferedReader(new FileReader(clusterfile));
                // reads the .km file line by line
                while ((tmpstr = docvecreader.readLine()) != null) {
                    /* if the string is empty - return all the words, which occur
                     in all the entries. empty string separates the list of words,
                     which are present in the document from the entries themselves*/
                    if (tmpstr.length() < 2) {
                        kc = hm.keySet();
                    } else if (tmpstr.contains("|")) {
                        // if there is | symbol, then we split the string and load nD vector for each entry
                        String[] parts = tmpstr.split("\\|");
                        names[nrows] = parts[0];
                        HashMap words = new HashMap();
                        
                        /* HashMap words stores a pair of a word and the number
                        of times it appeared in the particular entry ()*/
                        if (parts.length > 1) {
                            String vec[] = parts[2].split(",");
                            for (int l = 0; l < vec.length; l += 2) {
                                words.put(vec[l], new Double(vec[l + 1]));
                            }
                        }
                        
                        /* we create a matrix, where each row has the same length:
                         it is the number of words in the global word array. number
                         of rows is equal to the number of entries in the feeds*/
                        dv[nrows] = new double[kc.size()];
                        Iterator it = kc.iterator();
                        int j = 0;
                        while (it.hasNext()) {
                            String word = (String) it.next();
                            if (words.containsKey(word)) {
                                dv[nrows][j] = ((Double) words.get(word)).doubleValue();
                            } else {
                                dv[nrows][j] = 0.0;
                            }
                            j++;
                        }
                        nrows++;
                    } else {
                        /* as long as this is not line, which represents an rss
                         enrty - it must be a line, where is written, that such
                         word occures in the document so many times*/
                        String[] parts = tmpstr.split(",");
                        hm.put(parts[0], new Integer(parts[1]));
                    }
                }
                docvecreader.close();
            } catch (FileNotFoundException fne) {
                System.out.println("KmeansReadERROR: " + fne.getMessage());
                fne.printStackTrace();
            } catch (IOException ioe) {
                System.out.println("KMeansReadERROR: " + ioe.getMessage());
                ioe.printStackTrace();
            }
        }
        
        // here is where K-Mean analysis is performed
        int nclusters= new Integer(NClusters.getText()).intValue();
        ArrayList[] bestmatches = createKMeansClusters(nrows, dv, nclusters);
        Disp.setText("");
        
        //the output file
        tmpstr = clusterfile.getName().replace(".km", ".poiset");
        poisetfile = new File(".//data//POISET" + tmpstr);
        
        try {
        BufferedWriter poisetwr = new BufferedWriter(new FileWriter(poisetfile));
        poisetwr.write(nclusters+"\n");
        for (int i = 0; i < nclusters; i++) {
            int imax = 0, sv = 0;
            int nvecs = bestmatches[i].size();
            
            poisetwr.write("DOCUMENTS\n");
            Disp.append("Cluster [" + i + "] contains " + nvecs + " documents:\n");
            
            // saving and displaying the result
            HashMap chm = new HashMap();
            if (nvecs > 0) {
                for (int j = 0; j < nvecs; j++) {
                    vector = ((Integer) bestmatches[i].get(j)).intValue();
                    Disp.append("\t" + j + ". " + names[vector] + "\n");
                    int tloc=names[vector].indexOf("::");
                    poisetwr.write(names[vector].substring(0,tloc)+"\n");
                    String[] words = names[vector].toLowerCase().replaceAll("[\\d\\p{Punct}]+", " ").split("\\s");//.replaceAll(",,",",")
                    for (int k = 0; k < words.length; k++) {
                        if (swal.contains(words[k]) || words[k].isEmpty()) {
                            continue;
                        }
                        if (chm.containsKey(words[k])) {
                            sv = ((Integer) chm.get(words[k])).intValue();
                            sv += 1;
                            chm.put(words[k], new Integer(sv));
                            if (sv > imax) {
                                imax = sv;
                            }
                        } else {
                            chm.put(words[k], new Integer(1));
                        }
                    }
                }
                kc = chm.keySet();
                Iterator it = kc.iterator();
                int sum = 0;
                while (it.hasNext()) {
                    tmpstr = (String) it.next();
                    sum += ((Integer) chm.get(tmpstr)).intValue();
                }
                it = kc.iterator();
                Disp.append("sum = " + sum + ".  Of " + kc.size() + " terms, on average words appeared " +
                        sum / kc.size() + " times. The max was " + imax + " for this cluster.\n");
                Disp.append("When terms appear in less than half the documents they are weak\n");
                Disp.append("The following words are suggested:\n\t");
                poisetwr.write("TERMS\n");
                int k = 0;
                while (it.hasNext()) {
                    tmpstr = (String) it.next();
                    sv = ((Integer) chm.get(tmpstr)).intValue();
                    if (sv > imax / 4) {
                        Disp.append(tmpstr + "=" + sv + " , ");
                        poisetwr.write(tmpstr + "," + sv*1.0 + "\n");
                        k++;
                        if (k % 6 == 0) {
                            Disp.append("\n\t");
                        }
                    }
                }
                Disp.append("\n\n");
            }
        }
        poisetwr.close();
      }
      catch (FileNotFoundException fne) {
                System.out.println("KmeansWriteERROR: " + fne.getMessage());
                fne.printStackTrace();
      } catch (IOException ioe) {
                System.out.println("KMeansWriteERROR: " + ioe.getMessage());
                ioe.printStackTrace();
      }
    //operation is finished, lets set cursor to default
    setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
}//GEN-LAST:event_KMeansActionPerformed

    private void ClearPoiPlotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ClearPoiPlotActionPerformed
        // TODO add your handling code here:
        TabPanel.setSelectedComponent(POIComp);
        pPP1.removeAll();
        pPP1.validate();
        pPP1.repaint();
    }//GEN-LAST:event_ClearPoiPlotActionPerformed

    private void SavePoiPosActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_SavePoiPosActionPerformed
        // TODO add your handling code here:
        double[] loc;
        HashMap hm;
        try {
            BufferedWriter poilist = new BufferedWriter(new FileWriter(poifile));
            java.text.DecimalFormat formval = new java.text.DecimalFormat("#0.00");
            for (int i = 0; i < npoi; i++) {
                loc = pb[i].getcoords();
                poilist.write(formval.format(loc[0]) + "," + formval.format(loc[1]) + ",");
                poilist.write(pb[i].getBackground().getRed()+ ","+
                pb[i].getBackground().getGreen()+ ","+
                pb[i].getBackground().getBlue()+ ",");
                poilist.write(pb[i].getText() + ",");
                hm = pb[i].getPoiHashMap();
                Set kc = hm.keySet();
                Iterator it = kc.iterator();
                String tmpstr;
                while (it.hasNext()) {
                    tmpstr = (String) it.next();
                    poilist.write(tmpstr + "," + ((Double) hm.get(tmpstr)).doubleValue() + ",");
                }
                poilist.write("\n");
            }
            poilist.close();
        } catch (FileNotFoundException fne) {
        } catch (IOException ioe) {
        }
        
    }//GEN-LAST:event_SavePoiPosActionPerformed

    /* Requires RetrieveAllFeedsActionPerformed executed first. For all the entities
     in all the feeds generates a global array of word occurence. For each entity
     in all the feeds from the feedlist generates an array of words' occurence,
     checking, if the word is present in the global array. It calculates the
     similarities in meanings between all the entities in all the feeds.*/
    private void HashAllFeedEntriesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_HashAllFeedEntriesActionPerformed
        // sets the cursor symbol with a symbol, which shows that the software is busy
        setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR) );
        
        String FeedSetHStr = null;
        String[] entrywords;
        int nfeedentries = 0;
        double[][] allEntriesVec = new double[maxentries][];

        // selects text tab and clears it
        TabPanel.setSelectedComponent(TextComp);
        Disp.setText("");
        feeds = false;
        entries = true;
        
        /* combines the information from all the feeds into a single html document,
         having as an input a parsed structure from RetrieveAllFeedsActionPerformed*/
        for (int i = 0; i < nfeeds; i++) {
            FeedSetHStr += buildHtmlString(i);
        }
        //sets the progress of operation to 10%
        HashProg.setValue(10);
        
        /* create a set of the hash keys for all the feeds in the feedlist.
        hash consists of word occurence frequencies in the whole document,
         except if this is not a single word or not a stopword.*/
        HashMap AllEntHM = createHashMap(FeedSetHStr);
        Set kc = AllEntHM.keySet();
        
        // copies hashmap
        HashMap EntryHM = new HashMap(AllEntHM);
                double prog;

        for (int n = 0; n < nfeeds; n++) {
            // prints the title of the feed
            Disp.append("\n\n\n" + SFeed[n].getTitle() + "\n");
            
            //sets the progress of operation
            prog=50.0*((double)n/nfeeds);
            HashProg.setValue(10+(int)prog);
                           
            for (Iterator fit = SFeed[n].getEntries().listIterator(); fit.hasNext();) {
                Iterator hit = kc.iterator();
                // zeroing entries for the hash for a feed
                while (hit.hasNext()) {
                    EntryHM.put((String) hit.next(), new Integer(0));
                }
                
                SyndEntry oneEntry = (SyndEntry) fit.next();
                
                // prints the title for an entry in the feed
                Disp.append("\n" + oneEntry.getTitle() + "\n");
                
                // if the checkbox for Kmeans is selected
                if (KMeansSel){
                    /* constructs a string from the description and the title of
                     the enty. replaces all the html tags with spaces. replaces
                     all new lines and tabs with spaces */
                    Matcher docMatcher = tagPat.matcher(oneEntry.getTitle() +"::"+oneEntry.getDescription().getValue());
                    String tmpstr = docMatcher.replaceAll(" ");
                    EntryTitles[nfeedentries] = tmpstr.replaceAll("[\\r\\n\\t ]+", " ");
                }
                else{
                    // for a title of the entry, replaces all new lines and tabs with spaces
                    EntryTitles[nfeedentries] = (oneEntry.getTitle()).replaceAll("[\\n\\t]+", " ");
                }
                
                /* cleans the title and the decription from html tags, and splits
                 the result into words */
                Links[nfeedentries]=oneEntry.getLink();
                Matcher docMatcher = tagPat.matcher(oneEntry.getTitle() + oneEntry.getDescription().getValue());
                String tmpstr = docMatcher.replaceAll(" ");
                entrywords = tmpstr.toLowerCase().split("[\\s\\p{Punct}]+");
                
                /* updates the hash of the frequency of word occurrence for the
                 entity in the feed (only for words, which occur more than once
                 in the entity) */
                for (int i = 0; i < entrywords.length; i++) {
                    pstem.add(entrywords[i].toCharArray(), entrywords[i].length());
                    pstem.stem();
                    tmpstr = pstem.toString();
                    if (EntryHM.containsKey(tmpstr)) {
                        Integer storedVal = (Integer) EntryHM.get(tmpstr);
                        EntryHM.put(tmpstr, new Integer(storedVal.intValue() + 1));
                    }
                }
                
                /* generates a vector of occurences from a hashmap.
                 prints the vector of occurence for words in a single entity */
                allEntriesVec[nfeedentries] = createVector(EntryHM, kc);
                Disp.append("\n" + printdvec(allEntriesVec[nfeedentries]) + "\n");
                nfeedentries++;
            }
        }
        HashProg.setValue(80);
        
        /* calculates the matrix of similarities between entities for all feeds
         in the feedlist. calculates the distance in meanings between entitiesw */
        distMatrix = createDistMatrix(nfeedentries, allEntriesVec);
        
        // saves the calculated result
        if (KMeansSel){
            writeDocVecFile(-3, nfeedentries, allEntriesVec, AllEntHM);
        }
        else{
            writeDocVecFile(-2, nfeedentries, allEntriesVec, AllEntHM);
        }
        HashProg.setValue(100);
        // cumputation is finished, set cursor back to a normal one
        setCursor( java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR));
    }//GEN-LAST:event_HashAllFeedEntriesActionPerformed

    private void POIMagActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_POIMagActionPerformed
        // TODO add your handling code here:
        pPP1.setMag(new Integer(POIMag.getText()).intValue());
        MagSlider.setValue(new Integer(POIMag.getText()).intValue());
        plotDocs(true);
    }//GEN-LAST:event_POIMagActionPerformed

    private void MagSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_MagSliderStateChanged
        // TODO add your handling code here:
        pPP1.setMag(MagSlider.getValue());
        POIMag.setText(new Integer(MagSlider.getValue()).toString());
        plotDocs(false);
    }//GEN-LAST:event_MagSliderStateChanged

    private void KMeansCBActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_KMeansCBActionPerformed
        // TODO add your handling code here:
        KMeansSel = KMeansCB.isSelected();
    }//GEN-LAST:event_KMeansCBActionPerformed

    private void EditPOISetActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_EditPOISetActionPerformed
        // TODO add your handling code here:
        PoiEditor pe = new PoiEditor(this, true);
        pe.setVisible(true);
    }//GEN-LAST:event_EditPOISetActionPerformed
    // used to first plot docs versus pois on poi panel -- parallel process in PlotPanel POI
    private void plotDocs(boolean visible) {
        int x = pPP1.getWidth();
        int y = pPP1.getHeight();
        double dx = (double) x;
        double dy = (double) y;
        int mag = new Integer(POIMag.getText()).intValue();
        double[] loc = new double[2];
        for (int i = 0; i < ndocs; i++) {
            double di = (double) i;
            loc[0] = 0.0;
            loc[1] = 0.0;
            int red=0,green=0,blue=0;
            int attractions=0;
            if (visible) {
                Disp.append("dv[" + i + "] = ");
            }
            double[] attractMatrix = new double[npoi];
            for (int j = 0; j < npoi; j++) {
                double a = getAttraction(db[i].getdoubleVector(), pb[j].getdoubleVector());
                attractMatrix[pb[j].getNum()]=a;
                if (a>0.0) {
                    red+=pb[j].getBackground().getRed();
                    green+=pb[j].getBackground().getGreen();
                    blue+=pb[j].getBackground().getBlue();
                    attractions++;
                }
                if (visible) {
                    Disp.append(pb[j].getText() + "=" + a + ", ");
                }
                if (pb[j].isActive()) {
                    double[] p = pb[j].getcoords();
                    loc[0] += a * p[0] * mag;
                    loc[1] += a * p[1] * mag;
                }
            }
            if (visible) {
                Disp.append("\n");
            }

            if (loc[0] > .95) {
                loc[0] = .95 + (0.1*Math.random()-.05);
                //System.out.println("loc adjustment1 "+loc[0]);
            }
            if (loc[0] < -.95) {
                loc[0] = -.95 + (0.1*Math.random()-.05);
                //System.out.println("loc adjustment2 "+loc[0]);
            }
            if (loc[1] > .95) {
                loc[1] = .95 + (0.1*Math.random()-.05);
                //System.out.println("loc adjustment3 "+loc[1]);
            }
            if (loc[1] < -.95) {
                loc[1] = -.95 + (0.1*Math.random()-.05);
                //System.out.println("loc adjustment4 "+loc[1]);
            }
            if (loc[0] == 0.0 && loc[1] == 0.0) {
                loc[0] = -1.0 + ((double) i * 3.0 / (double) x);
                loc[1] = -1.0;
            }
            db[i].setcoords(loc[0], loc[1]);
            if (attractions==0){
             db[i].setBackground(new java.awt.Color(255,255,255));   
            }
            else{
             db[i].setBackground(new java.awt.Color(red/attractions,green/attractions,blue/attractions));   
            }
            
            db[i].setAttractMatrix(attractMatrix);
        }
        pPP1.validate();
        pPP1.repaint();
    }
    // used by POIPanel to calculate attraction between POIS and docs
    private double getAttraction(double[] document, double[] poi) {
        double attraction = 0.0;
        double factor = (double) document.length;
        for (int i = 0; i < document.length; i++) {
            if (document[i] > 0 && poi[i] > 0) {
                attraction += (document[i] * poi[i]) / factor;
            }
        }
        //double distance = Math.sqrt(sum);
        //return (1 / (1 + distance));
        return attraction;
    }
    
    // takes the hashmap and related doc vectors and generates a file
    private void writeDocVecFile(int num, int size, double[][] in, HashMap hm) {
        String tmpstr;
        if (num == -3) {//indicates it is all entries in all feeds for KMeans Clustering
            tmpstr = feedfile.getName().replace(".flst", ".km");
            vecfile = new File(".//data//KMAE" + tmpstr);
        }
        if (num == -2) {//indicates it is all entries in all feeds
            tmpstr = feedfile.getName().replace(".flst", ".vec");
            vecfile = new File(".//data//AllEntries" + tmpstr);
        }
        if (num == -1) {//indicates it is a summary of feeds
            tmpstr = feedfile.getName().replace(".flst", ".vec");
            vecfile = new File(".//data//" + tmpstr);
        }
        if (num >= 0) {// it is the current feed
            tmpstr = SFeed[num].getTitle().replaceAll("[\\s\\p{Punct}]+", "");
            vecfile = new File(".//data//" + tmpstr + ".vec");
        }
        try {
            BufferedWriter vecwr = new BufferedWriter(new FileWriter(vecfile));
            Set ks = hm.keySet();
            // System.out.println("Vector size = "+in[1].length);
            Iterator it = ks.iterator();
            int k = 0;
            while (it.hasNext()) {
                tmpstr = (String) it.next();
                vecwr.write(tmpstr + "," + hm.get(tmpstr) + "\n");
            }
            vecwr.write("\n");
            for (int i = 0; i < size; i++) {
                if (num == -1) {//indicates it is a summary of feeds
                    tmpstr = SFeed[i].getTitle().replaceAll("[\\n\\t\\s]+", "");
                } else {// it is the current feed
                    tmpstr = EntryTitles[i].replaceAll("\\|", ":");
                }
                vecwr.write(tmpstr + "|");
                tmpstr = Links[i].replaceAll("\\|", ":");
                vecwr.write(tmpstr + "|");
                int j = 0;
                // System.out.println("keyset size = "+ks.size());
                Iterator lit = ks.iterator();
                while (lit.hasNext()) {
                    String tpstr = (String) lit.next();
                    if (j < in[1].length && in[i][j] > 0) {
                        vecwr.write(tpstr + "," + in[i][j] + ",");
                    }
                    j++;
                }
                // System.out.println();
                vecwr.write("\n");
            }
            vecwr.close();
        } catch (FileNotFoundException fne) {
        } catch (IOException ioe) {
        }
    }
    
    private String buildHtmlString(int cf) {
    /* gets data from the rome syndication feed and builds a little html string
     for display or processing*/
        String LStr = new String("<html><head><title>RSS</title></head>\n<body><ul>");
        for (Iterator iter = SFeed[cf].getEntries().listIterator(); iter.hasNext();) {
            SyndEntry myentry = (SyndEntry) iter.next();
            LStr += "<h3>" + myentry.getTitle() + "</h3>\n<li>";
            LStr += "<a href = \"" + myentry.getLink() + "\">More Info</a>\n";
            LStr += "<div>" + myentry.getDescription().getValue() + "</div>";
            LStr += "</li>";
        }
        LStr += "</ul></body></html>";
        return LStr;
    }
    
    /* creates a hashmap for a given string which is an XML document. the method
     calculates the frequency of occurences of each word in the document. it
     skips those words which occure only once or are among stopwords*/
    private HashMap createHashMap(String input) {
 
        Set kc;
        Iterator it;
        HashMap hm = new HashMap();
        String tmpstr, tmpstr2 = new String();
        
        String[] wordlist;
        int max = 0;

        /* performs match operations on a character sequence by interpreting a
         Pattern. We are looking for a structure like "<"+"any group of symbols"+">"
         and replace them with spaces, or in other words - elliminating XML tags.
         Later we simply split information into an array.*/
        Matcher dm = tagPat.matcher(input);
        tmpstr = dm.replaceAll(" ");
        wordlist = tmpstr.toLowerCase().split("[\\s\\d\\p{Punct}]+");
        
        // create a hash of the frequency of word occurrence
        /*code for a parser system
        for (int i = 0; i < wordlist.length; i++) {
        tmpstr2 += wordlist[i] + " ";  }
        System.out.println("Before stemming"+tmpstr2);        
        nlparser.RemoveWord(wordlist, Articles);
        nlparser.toStemmer(wordlist, Verb);
        nlparser.toStemmer(wordlist, Adj);
        nlparser.toStemmer(wordlist, Adv);
        nlparser.toStemmer(wordlist, Noun);
        tmpstr2=new String();
        for (int i = 0; i < wordlist.length; i++) {
        tmpstr2 += wordlist[i] + " ";}
        System.out.println("After Stemming"+tmpstr2); 
         */
        
        for (int i = 0; i < wordlist.length; i++) {
            //code for a porter stemmer
            pstem.add(wordlist[i].toCharArray(), wordlist[i].length());
            pstem.stem();
            tmpstr = pstem.toString();
            
            /* checking the presence of a word in the Hash Map. If it is already in,
             we increase the counter. If it is absent - we merely add the word to the Hash */
            if (hm.containsKey(tmpstr)) {
                Integer storedVal = (Integer) hm.get(tmpstr);
                if ((storedVal.intValue() + 1) > max) {
                    max = storedVal.intValue() + 1;
                }
                hm.put(tmpstr, new Integer(storedVal.intValue() + 1));
            } else {
                hm.put(tmpstr, new Integer(1));
            }
        }
        
        Disp.append("\nMap Size before cleaning is " + hm.size());
        
        /* If the word occurs only once, or if it is within a StopWord Array,
         then we remove the word, clearning the HashMap*/
        kc = hm.keySet();
        it = kc.iterator();
        while (it.hasNext()) {
            tmpstr = (String) it.next();
            /* if (((Integer) hm.get(tmpstr)).intValue() < (int) (max * .05) ||
            ((Integer) hm.get(tmpstr)).intValue() > (int) (max * .85)) */
            if (swal.contains(tmpstr) || ((Integer) hm.get(tmpstr)).intValue() == 1) {
                it.remove();
            }
        }

        Disp.append("\nMap Size after cleaning is " + hm.size());
        return hm;

    }
    // creates a sub document vector based on a major document hashmap
    private double[] createVector(HashMap hm, Set kc) {
        Iterator it = kc.iterator();

        int j = 0;
        double[] docVec = new double[hm.size()];
        while (it.hasNext()) {
            String word = (String) it.next();
            docVec[j++] = ((Integer) hm.get(word)).doubleValue();
        }
        return docVec;
    }
    // return an array of the items in a set of clusters
    private ArrayList[] createKMeansClusters(int nrows, double[][] vectors, int nclusters) {
        int vecsize = vectors[0].length;
        
        //determine max values for each axis -- min in this app is always 0.0
        double[] max = new double[vecsize];
        for (int i = 0; i < nrows; i++) {
            for (int j = 0; j < vecsize; j++) {
                if (vectors[i][j] > max[j]) {
                    max[j] = vectors[i][j];
                }
            }  
        }
        //Randomly place the requested number of cluster points in the space
        double[][] clusterpoint = new double[nclusters][vecsize];
        for (int i = 0; i < nclusters; i++) {
            for (int j = 0; j < vecsize; j++) {
                clusterpoint[i][j] = Math.random() * max[j] / (double) nrows;
            }
        }
        // create an array of array lists and initialize the members 
        // used after the first iuteration to store results for comparison
        ArrayList[] lastmatches = new ArrayList[nclusters];
        for (int i = 0; i < nclusters; i++) {
            lastmatches[i] = new ArrayList();
        }
        // create an array of array lists 
        // to store which vectors are closest to the clusterpoints
        ArrayList[] bestmatches = new ArrayList[nclusters];
        // this loop will take up to 50 efforts to find cluster centerpoints.
        for (int k = 0; k < 50; k++) {
            // initialize the arraylist for teh clusters
            for (int i = 0; i < nclusters; i++) {
                bestmatches[i] = new ArrayList();
            }
            // iterate across the vectors find which cluster point is closest to each vector
            // bestmatch is the cluster index and j is the vector index 
            for (int j = 0; j < nrows; j++) {
                int bestmatch = 0;
                for (int i = 0; i < nclusters; i++) {
                    double d = getDistance(clusterpoint[i], vectors[j]);
                    if (d < getDistance(clusterpoint[bestmatch], vectors[j])) {
                        bestmatch = i;
                    }
                }
                bestmatches[bestmatch].add(new Integer(j));
            }

            // rather convoluted code to check and see if the cluster array lists are equal
            // if all the array lists match, there is no change and we break
            // basically if all lists are the same, matchcounter == nclusters at the end
            int matchcounter = 0;
            for (int i = 0; i < nclusters; i++) {
                matchcounter++;
                if (!bestmatches[i].equals(lastmatches[i])) {
                    break;
                }
            }
            if (matchcounter == nclusters) {
                break;
            }
            //assuming the above break was not activated, we need to prpare to iterate again
            //first copy the existing match sets to the comparison arrays
            for (int i = 0; i < nclusters; i++) {
                lastmatches[i] = bestmatches[i];
            }
            // move the clusterpoint based on the average of members positions
            double[] avgs;
            for (int i = 0; i < nclusters; i++) {
                avgs = new double[vecsize];
                int nvecs = bestmatches[i].size();
                if (nvecs > 0) {
                    int vector;
                    for (int j = 0; j < nvecs; j++) {
                        vector = ((Integer) bestmatches[i].get(j)).intValue();
                        for (int n = 0; n < vecsize; n++) {
                            avgs[n] += vectors[vector][n];
                        }
                    }
                    for (int n = 0; n < vecsize; n++) {
                        clusterpoint[i][n] = avgs[n] / (double) nvecs;
                    }
                }
            }// end of cluster point movement to average
        }//end of the iteration loop
        return bestmatches;
    }
    // plots a distance map for a given 2d vector
    private double[][] createDistMatrix(int s, double[][] in) {
        double[][] dm = new double[s][s];
        double d = 0.0;
        String value;
        java.text.DecimalFormat formval = new java.text.DecimalFormat("#00.00");

        Disp.append("\n**** " + s + " ****\n"); // printi the size of the matrix
        for (int i = 0; i < s; i++) {
            Disp.append("\t" + (i + 1));
        }
        Disp.append("\n");
        for (int i = 0; i < s; i++) {
            Disp.append((i + 1) + "\t");
            /* we would like to know, how entities in the feed correlate with
             each other or how thay are distinct*/
            for (int n = 0; n < s; n++) {
                value = new String();
                if (PDist.isSelected()) {
                    d = getPearsonCorrelation(in[i], in[n]);
                }
                if (EDist.isSelected()) {
                    d = getSimDistance(in[i], in[n]);
                }
                dm[i][n] = d;
                value = formval.format(d);
                Disp.append(value + "\t");
            }
            Disp.append("\n");
        }
        return dm;
    }
    // uses euclidian distance to calculate distance between two docs 0-same, 1 = great
    private double getSimDistance(double[] scores1, double[] scores2) {
        double sum = 0.0;
        for (int i = 0; i < scores1.length; i++) {
            sum += Math.pow((scores2[i] - scores1[i]), 2.0);

        }
        double distance = Math.sqrt(sum);
        return 1.0 - (1.0 / (1.0 + distance));
    }
    //does a true euclidian distance measure -- 0 means same
    private double getDistance(double[] scores1, double[] scores2) {
        double sum = 0.0;
        for (int i = 0; i < scores1.length; i++) {
            sum += Math.pow((scores2[i] - scores1[i]), 2.0);

        }
        double distance = Math.sqrt(sum);
        return distance;
    }
    // variation on PC -- 0= same 1 = no similarity
    private double getPearsonCorrelation(double[] scores1, double[] scores2) {
        double result = 0;
        double sum_sq_x = 0;
        double sum_sq_y = 0;
        double sum_coproduct = 0;
        double mean_x = scores1[0];
        double mean_y = scores2[0];
        for (int i = 2; i < scores1.length + 1; i += 1) {
            double sweep = Double.valueOf(i - 1) / i;
            double delta_x = scores1[i - 1] - mean_x;
            double delta_y = scores2[i - 1] - mean_y;
            sum_sq_x += delta_x * delta_x * sweep;
            sum_sq_y += delta_y * delta_y * sweep;
            sum_coproduct += delta_x * delta_y * sweep;
            mean_x += delta_x / i;
            mean_y += delta_y / i;
        }
        double pop_sd_x = (double) Math.sqrt(sum_sq_x / scores1.length);
        double pop_sd_y = (double) Math.sqrt(sum_sq_y / scores1.length);
        double cov_x_y = sum_coproduct / scores1.length;
        if (pop_sd_x * pop_sd_y == 0.0) {
            return 1.0;
        } else {
            return Math.abs(1.0 - cov_x_y / (pop_sd_x * pop_sd_y));
        }
    }
    // create a string representation of an array
    private String printivec(int[] a) {
        String matrix = new String("{");
        for (int i = 0; i < a.length; i++) {
            matrix += a[i] + ",";
        }
        return matrix.substring(0, matrix.length() - 1) + "}";
    }
    // create a string representation of an array
    private String printdvec(double[] a) {
        // String matrix = new String("{");
       StringBuffer matrix = new StringBuffer("{");
        int size = a.length;
        for (int i = 0; i < size; i++) {
            matrix.append(a[i] + ",");
        }
        return matrix.substring(0, matrix.length() - 1) + "}";
    }
    // initialize tagpattern, load a default feed, load stop word list
    private void setDefaults() {
        // this is the regular expression pattern used to strip html tags from strings
        //it is used in create hashmap
        tagPat = Pattern.compile("<[^>]*>");
        // this looks for a default feed list file in a data subdirectory of the running diretcory
        // the data subdirectory is used for all data files 
        pPP1.addComponentListener(pPP1);
        feedfile = new File(".//data//RSSdefault.flst");
        if (feedfile.exists()) {
            try {

                BufferedReader rssfeeds = new BufferedReader(new FileReader(feedfile));
                int i = 0;
                while ((FeedNames[i] = rssfeeds.readLine()) != null) {
                    flm.addElement(FeedNames[i]);
                    i++;
                }
                FeedList.setModel(flm);
                rssfeeds.close();
            } catch (FileNotFoundException fne) {
            } catch (IOException ioe) {
            }
        }
        // this loads an arraylist with a set op stopwords used in the createhashmap function
        swlfile = new File(".//resources//stoplist.dat");
        String tmpstr;
        if (swlfile.exists()) {
            try {

                BufferedReader swlreader = new BufferedReader(new FileReader(swlfile));
                int i = 0;
                while ((tmpstr = swlreader.readLine()) != null) {
                    pstem.add(tmpstr.toCharArray(), tmpstr.length());
                    pstem.stem();
                    tmpstr = pstem.toString();
                    swal.add(tmpstr);
                }
                swlreader.close();
            } catch (FileNotFoundException fne) {
            } catch (IOException ioe) {
            }
        }
    /*load resourses for the nlp parser    
    Articles = nlparser.GetStrings("resources/DT.txt");
    Verb = nlparser.GetStems("resources/stemmer/verb.exc");
    Adj = nlparser.GetStems("resources/stemmer/adj.exc");
    Adv = nlparser.GetStems("resources/stemmer/adv.exc");
    Noun = nlparser.GetStems("resources/stemmer/noun.exc");
     */
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new FeedAnalyzer().setVisible(true);

            }
        });
    }
    //Global Variable declaration
    //Limits on number of RSS entries in all feeds, number of feeds, and number of POIS
    //At some point, this should be made dynamic
    final int maxentries = 1500;
    final int maxfeeds = 100;
    final int maxpoi = 20;
    //PStemmer is a class that implements a Porter stemmer
    PStemmer pstem = new PStemmer();
    //The NLPParser is not currenly used, 
    //it has been commented out where it might be used
    //the articles, verbs, etc arrays support the stemmer
    NLPParser nlparser = new NLPParser();
    String Articles[];
    String Verb[][];
    String Adj[][];
    String Adv[][];
    String Noun[][];
    //The POI Button(Point Of Interest) and DVButton(DocumentVector) classes extend buttons 
    // and serve painitng functions along with several panel subclasses --
    //PlotPanel1, PlotPnael2, and PlotPanelPOI
    //The POIBut class is slightly more developed than the DVBut class
    //The PlotPanelPOI is much more complex than the other two which served
    //Primarily to test the MultiDimensional Scaling Algorithm
    POIBut[] pb = new POIBut[maxpoi];
    DVBut[] db = new DVBut[maxentries];
    
    //The StopWordArrayList (swal) is loaded at startup and used to eliminate stopwords
    //It is used a couple places, but primarily in making hash maps
    ArrayList swal = new ArrayList();
    int curFeed = 0, nfeeds = 0, npoi = 0, ndocs = 0;
    //This tagpattern is used to eliminate html tags from text
    Pattern tagPat;
    // These files are used across methods to read and write 
    // lists of RSS feeds -- feedfile, lists of POIs, poifile
    // lists of prepared vector files (word vector, and entry vectors) vecfile
    // and stop words
    File feedfile, poifile, vecfile, swlfile;
    // a global from the rate text filed that can be accessed by plot panel
    double rate;
    boolean feeds = false, entries = false;
    boolean KMeansSel = false;
    double[][] distMatrix = null;
    String FeedNames[] = new String[maxfeeds];
    String EntryTitles[] = new String[maxentries];
    String Links[] = new String[maxentries];
    SyndFeed SFeed[] = new SyndFeed[maxfeeds];
    SyndFeedInput SFInput = new SyndFeedInput(); // An instance to parse XML, from JDOM library
    javax.swing.DefaultListModel flm = new javax.swing.DefaultListModel(); // Creates a List with its content
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton AddFeed;
    private javax.swing.JButton ClearDisplay;
    private javax.swing.JButton ClearEditor;
    private javax.swing.JButton ClearPoiPlot;
    private javax.swing.JTextArea Disp;
    private javax.swing.ButtonGroup DistMeasure;
    private javax.swing.JRadioButton EDist;
    private javax.swing.JButton EditPOISet;
    private javax.swing.JTextField Error;
    private javax.swing.JLabel ErrorL;
    private javax.swing.JButton Exit;
    private javax.swing.JLabel Feed;
    private javax.swing.JLabel FeedAnalysis;
    private javax.swing.JList FeedList;
    private javax.swing.JProgressBar FeedLoadProg;
    private javax.swing.JTextField FeedToAdd;
    private javax.swing.JButton GetEntryInfo;
    private javax.swing.JButton GetFeedInfo;
    private javax.swing.JButton GetRawFeed;
    private javax.swing.JLabel HTML;
    private javax.swing.JScrollPane HTMLComp;
    private javax.swing.JButton HashAllFeedEntries;
    private javax.swing.JButton HashAllFeeds;
    private javax.swing.JButton HashOneFeedEntries;
    private javax.swing.JProgressBar HashProg;
    private javax.swing.JEditorPane HtmlDisp;
    private javax.swing.JTextField Iter;
    private javax.swing.JLabel IterL;
    private javax.swing.JButton KMeans;
    private javax.swing.JCheckBox KMeansCB;
    private javax.swing.JButton LoadDocVec;
    private javax.swing.JButton LoadFeeds;
    private javax.swing.JButton LoadPOI;
    private javax.swing.JButton LoadRSS;
    private javax.swing.JSlider MagSlider;
    private javax.swing.JTextField NClusters;
    private javax.swing.JRadioButton PDist;
    private javax.swing.JScrollPane POIComp;
    private javax.swing.JTextField POIMag;
    private javax.swing.JButton Plot;
    private javax.swing.JScrollPane PlotComp;
    private javax.swing.JScrollPane PlotCompFin;
    private javax.swing.JLabel PlotL;
    private javax.swing.JLabel PoiPower;
    private javax.swing.JLabel RSSList;
    private javax.swing.JTextField Rate;
    private javax.swing.JLabel RateL;
    private javax.swing.JButton RemoveFeed;
    private javax.swing.JButton ReoadRSS;
    private javax.swing.JButton RetrieveAllFeeds;
    private javax.swing.JButton RetrieveFeed;
    private javax.swing.JButton SaveFeeds;
    private javax.swing.JButton SavePoiPos;
    private javax.swing.JTabbedPane TabPanel;
    private javax.swing.JScrollPane TextComp;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JSeparator jSeparator3;
    private javax.swing.JSeparator jSeparator4;
    private javax.swing.JSplitPane jSplitPane1;
    private spring.PlotPanel1 pP1;
    private spring.PlotPanel2 pP2;
    private spring.PlotPanelPOI pPP1;
    // End of variables declaration//GEN-END:variables
}
